home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Games / Glider 3.14 / source / Glider parts ƒ / F-GliderMain.p < prev    next >
Encoding:
Text File  |  1993-06-03  |  29.5 KB  |  892 lines  |  [TEXT/PJMM]

  1. unit GliderMain;
  2.  
  3. interface
  4.     uses
  5.         Dialogs, Sound, GameUtilities;
  6.  
  7.     procedure HandleCandle;
  8.     procedure ComputeGliderPos;
  9.     procedure DrawGlider;
  10.     procedure DoGliderBitesIt;
  11.     procedure DotheHoopla;
  12.     procedure GetSet;
  13.     procedure WrapUpaGame;
  14.     procedure DoFinalScore;
  15.     procedure WelcomeToNextLevel;
  16.     procedure DetermineObstacle (whasUp: Integer);
  17.     procedure ComputeStatus;
  18.     procedure DoDyingDisplay;
  19.     procedure DoCopter;
  20.     procedure DoDrip;
  21.     procedure DoCat;
  22.  
  23. implementation
  24.  
  25.     var
  26.         tempRect: Rect;                {Temporary rectangle    }
  27.         Index: Integer;                {For looping                }
  28.         CtrlHandle: controlhandle;    {Control handle            }
  29.  
  30. {=================================}
  31.  
  32.     procedure HandleCandle;
  33.         var
  34.             index: Integer;
  35.     begin
  36.         for index := 1 to numberOfCandles do
  37.             begin
  38.                 candleInfo[index, 2] := candleInfo[index, 2] + 1;    {Increment the "mode"}
  39.                 case candleInfo[index, 2] of                            {And depending on the mode, we'll        }
  40.                     0..2, 4:                                                     {either idle this pass through the loop...    }
  41.                         begin
  42.                         end;
  43.                     3:                                                             {or we'll draw a new flame state!        }
  44.                         begin
  45.                             DrawAnObject(7, candleInfo[index, 0], candleInfo[index, 1])
  46.                         end;
  47.                     5: 
  48.                         begin
  49.                             DrawAnObject(14, candleInfo[index, 0], candleInfo[index, 1])
  50.                         end;
  51.                     otherwise
  52.                         candleInfo[index, 2] := -1;
  53.                 end;    {case candleInfo[index, 2] of}
  54.             end;
  55.     end;
  56.  
  57. {=================================}
  58.  
  59.     procedure ComputeGliderPos;
  60.     begin
  61.         if (stalling) then
  62.             begin
  63.                 moveHori := stall;        {Simple. }
  64.             end
  65.         else
  66.             begin
  67.                 moveHori := thrust;
  68.             end;
  69.         moveVert := gravity;
  70.     end;
  71.  
  72. {=================================}
  73.  
  74.     procedure DrawGlider;
  75.         var
  76.             mode, shadoMode: Integer;
  77.             tempRect, temp2Rect: Rect;
  78.     begin
  79.         if (gliderCraft) then            {Here is where we do the flicker-free animation.    }
  80.             begin                            {First we go through some bogus conditionals to    }
  81.                 shadoMode := 53;                {get the proper objects from the objectMap...        }
  82.                 if (stalling) then
  83.                     mode := 1
  84.                 else
  85.                     mode := 0;
  86.                 if (burning) then
  87.                     mode := 37 + burnMode;
  88.                 if (crushed) then
  89.                     mode := 35;
  90.             end
  91.         else
  92.             begin
  93.                 mode := 2;
  94.                 shadoMode := 54;
  95.                 if (burning) then
  96.                     mode := 56 + burnMode;
  97.                 if (crushed) then
  98.                     mode := 55;
  99.             end;
  100. {Step 1, find the smallest rect that encloses both the new position of the shadow and the old.    }
  101.         UnionRect(shadowDropRect, oldShadowRect, tempRect);
  102. {Step 2, Copy that swatch of background from the virginMap to the loadMap for assembly.    }
  103.         CopyBits(virginMap, loadMap, tempRect, tempRect, srcCopy, nil);
  104. {But before we do, let's do Step 1 and 2 for the glider as well.  This way there's no way we    }
  105.         UnionRect(playerDropRect, oldPlayerRect, temp2Rect);
  106. {will cover up the shadow with the background behind the glider (during those LOW glides)        }
  107.         CopyBits(virginMap, loadMap, temp2Rect, temp2Rect, srcCopy, nil);
  108. {Step 3, Mask the shadow from the objectMap to it's swatch of background on the loadMap    }
  109.         CopyMask(objectsMap, objectsMap, loadMap, objectsRects[shadoMode, 0], objectsRects[shadoMode, 1], shadowDropRect);
  110. {Ditto for the glider.  Now both shadow & glider are assembled and ready for visibility.        }
  111.         CopyMask(objectsMap, objectsMap, loadMap, objectsRects[mode, 0], objectsRects[mode, 1], playerDropRect);
  112. {Step 4, grab the whole assembled shadow (with surrounding bckgrnd) and dump to on screen.}
  113.         CopyBits(loadMap, mainWindow^.portBits, tempRect, tempRect, srcCopy, mainWindow^.visRgn);
  114. {Ditto for the glider.  Only these last 2 steps are seen by the player.  Flickerless movement!    }
  115.         CopyBits(loadMap, mainWindow^.portBits, temp2Rect, temp2Rect, srcCopy, mainWindow^.visRgn);
  116.     end;
  117.  
  118. {=================================}
  119.  
  120.     procedure DoGliderBitesIt;
  121.         var
  122.             Index: Integer;
  123.             tempRect: Rect;
  124.     begin
  125.         DoTheSound('boom.snd', highPriority);
  126.         gliderNumber := gliderNumber - 1;            {Subtract 1 from number of gliders player has.    }
  127.         SetPort(mainWindow);
  128.         for Index := 1 to 30 do
  129.             begin
  130.                 SetRect(tempRect, 24 + playerDropRect.left - Index * 2, 11 + playerDropRect.top - Index * 2, 24 + playerDropRect.left + Index * 2, 11 + playerDropRect.top + Index * 2);
  131.                 InvertOval(tempRect);
  132.             end;
  133.         for Index := 1 to 30 do
  134.             begin
  135.                 SetRect(tempRect, 24 + playerDropRect.left - Index * 2, 11 + playerDropRect.top - Index * 2, 24 + playerDropRect.left + Index * 2, 11 + playerDropRect.top + Index * 2);
  136.                 InvertOval(tempRect);
  137.             end;
  138.         if (gliderNumber < 1) then                        {i.e. "If the player is out of gliders then...."        }
  139.             begin
  140.                 DoFinalScore;                                    {Show the player the final score, etc.                }
  141.             end
  142.         else                                                {Otherwise... we're dead but not finished...the        }
  143.             begin                                            {player has more gliders still.                        }
  144.                 Stalling := FALSE;
  145.                 ResetGliderPos;
  146.                 FoldTheGlider;
  147.                 GetSet;                                            {Now call on GetSet to do the rest (not once-only)    }
  148.             end;
  149.     end;
  150.  
  151. {=================================}
  152.  
  153.     procedure DotheHoopla;                        {If the player makes it through the last room,    }
  154.         var                                            {we call this little animation sequence.            }
  155.             index, index2, mode: Integer;                {You can examine it if you like, but it's just    }
  156.             dummyRect: Rect;                            {more of the same tedious rect manipulation.    }
  157.             gliderRects: array[1..30, 0..1] of Rect;
  158.     begin
  159.         for index := 1 to 30 do
  160.             begin
  161.                 if (gliderCraft) then
  162.                     begin
  163.                         SetRect(gliderRects[index, 0], 0, 0, 46, 19);
  164.                         mode := 0;
  165.                     end
  166.                 else
  167.                     begin
  168.                         SetRect(gliderRects[index, 0], 0, 0, 65, 22);
  169.                         mode := 2;
  170.                     end;
  171.                 OffsetRect(gliderRects[index, 0], DoRandom(1000) - 1000, DoRandom(260) + 20);
  172.                 gliderRects[index, 1] := gliderRects[index, 0];
  173.             end;
  174.         PenNormal;
  175.         PenMode(patXOr);
  176.         SetPort(virginPort);
  177.         FillRect(virginPort^.portRect, black);
  178.         for index := 1 to 1000 do
  179.             begin
  180.                 MoveTo(DoRandom(512), DoRandom(320));
  181.                 Line(0, 0);
  182.             end;
  183.         SetPort(mainWindow);
  184.         FillRect(mainWindow^.portRect, black);
  185.         TextFont(0);                        {Set font to Chicago (everyone has this font)        }
  186.         TextSize(12);                    {Make it 12 point in size so that it isn't cruddy    }
  187.         TextMode(srcXOr);
  188.         MoveTo(300, 293);
  189.         DrawString('At last you are free!');
  190.         for index2 := 1 to 160 do
  191.             begin
  192.                 for index := 1 to 30 do
  193.                     begin
  194.                         OffsetRect(gliderRects[index, 0], 10, -1);
  195.                         UnionRect(gliderRects[index, 0], gliderRects[index, 1], dummyRect);
  196.                         CopyBits(virginMap, loadMap, dummyRect, dummyRect, srcCopy, nil);
  197.                         CopyMask(objectsMap, objectsMap, loadMap, objectsRects[mode, 0], objectsRects[mode, 1], gliderRects[index, 0]);
  198.                     end;
  199.                 for index := 1 to 30 do
  200.                     begin
  201.                         UnionRect(gliderRects[index, 0], gliderRects[index, 1], dummyRect);
  202.                         CopyBits(loadMap, mainWindow^.portBits, dummyRect, dummyRect, srcCopy, mainWindow^.visRgn);
  203.                         gliderRects[index, 1] := gliderRects[index, 0];
  204.                     end;
  205.             end;
  206.     end;
  207.  
  208. {=================================}
  209.  
  210.     procedure GetSet;
  211.         var
  212.             index: Integer;
  213.             dummyLong: LongInt;
  214.     begin
  215.         extraGlider := FALSE;
  216.         extraTime := FALSE;
  217.         darkOn := FALSE;
  218.         switchUntouched := TRUE;
  219.         Stalling := FALSE;
  220.         burning := FALSE;
  221.         crushed := FALSE;
  222.         moveHori := 0;
  223.         moveVert := 0;
  224.         gameTime := 0;
  225.         dripMode := 0;
  226.         dripCycle := 23;
  227.         catMode := 0;
  228.         numberOfCopters := (levelOn div 10) + 1;
  229.         if (levelOn > 13) then
  230.             numberOfCopters := 1;
  231.         for index := 1 to numberOfCopters do
  232.             copterMode[index, 0] := DoRandom((18 - levelOn) * 8) + (18 - levelOn) * 6;
  233.         SetRect(vitalArea, playerDropRect.left + 5, playerDropRect.top + 10, playerDropRect.left + 43, playerDropRect.top + 15);
  234.         UpDate_GliderMain;
  235.         DrawGlider;
  236.         Delay(90, dummyLong);
  237.     end;
  238.  
  239. {=================================}
  240.  
  241.     procedure WrapUpaGame;
  242.         var
  243.             index, ranking: Integer;
  244.             theOverflow: LongInt;
  245.             tempString, fixedScore, padding: Str255;
  246.     begin
  247.         FlushEvents(everyEvent, 0);                                    {Clear all the keystrokes    }
  248.         if (theScore > hiScores[10]) then        {Is it a high score?            }
  249.             begin
  250.                 scoresChanged := TRUE;                                        {Mark scores as changed    }
  251.                 DoTheSound('bonus.snd', highPriority);                            {Play the bonus sound.        }
  252.                 ranking := 10;                                                {And sort through the high    }
  253.                 for index := 9 downto 1 do                                {scores to find the players    }
  254.                     begin                                                        {ranking.                        }
  255.                         if (theScore > hiScores[index]) then
  256.                             ranking := index;
  257.                     end;
  258.                 for index := 10 downto ranking + 1 do
  259.                     begin
  260.                         hiScores[index] := hiScores[index - 1];                {Move everyone's score        }
  261.                         hiStrings[index] := hiStrings[index - 1];                {down the list.                }
  262.                     end;
  263.                 hiScores[ranking] := theScore;
  264.                 WhosHiScore(nameUsing);
  265.                 hiStrings[ranking] := nameUsing;
  266.                 if (theScore > 999999) then
  267.                     begin
  268.                         theOverflow := (theScore div 1000000) * 1000000;
  269.                         theScore := theScore - theOverflow;
  270.                     end;
  271.             end;
  272.         playing := FALSE;
  273.         switchUntouched := TRUE;
  274.         darkOn := FALSE;
  275.         burning := FALSE;
  276.         crushed := FALSE;
  277.         stalling := FALSE;
  278.         for index := 1 to numberOfCopters do
  279.             SetRect(coptersRects[index, 0], 0, 0, 0, 0);
  280.         ResetGliderPos;
  281.         levelOn := levelBegin;
  282.         Update_GliderMain;
  283.         EnableItem(GetMenu(L_Game), 1);
  284.         EnableItem(GetMenu(L_Game), 2);
  285.         DisableItem(GetMenu(L_Game), 4);
  286.         DisableItem(GetMenu(L_Game), 5);
  287.         EnableItem(GetMenu(L_Options), 0);
  288.         SetItem(GetMenu(l_Game), 4, 'Pause');
  289.         SetPort(oldPort);
  290.         RedrawHiScores;
  291.     end;
  292.  
  293. {=================================}
  294.  
  295.     procedure DoFinalScore;
  296.         var
  297.             index: Integer;
  298.             dummyLong: LongInt;
  299.             dummyRect, dummyRect2, dummyRect3: Rect;
  300.             dummyString, dummyString2: Str255;
  301.     begin
  302.         SetPort(loadPort);
  303.         EraseRect(loadMap.bounds);
  304.         SetRect(dummyRect, 0, 0, 0, 0);
  305.         ResizeARect(dummyRect, 34);
  306.         CopyBits(objectsMap, loadMap, objectsRects[34, 0], dummyRect, srcCopy, nil);
  307.         PenNormal;
  308.         TextFont(0);
  309.         TextSize(12);
  310.         MoveTo(60, 15);
  311.         if levelOn > maxLevel then
  312.             begin
  313.                 DoTheSound('bonus.snd', highPriority);
  314.                 dummyString := 'You made it!  Final score ';
  315.                 theScore := theScore + 1000 * gliderNumber;
  316.             end
  317.         else
  318.             begin
  319.                 dummyString := 'Final score ';
  320.             end;
  321.         NumToString(theScore, dummyString2);
  322.         dummyString := CONCAT(dummyString, dummyString2);
  323.         DrawString(dummyString);
  324.         dummyRect2 := dummyRect;
  325.         OffsetRect(dummyRect2, 512, 290);
  326.         dummyRect3 := dummyRect2;
  327.         dummyRect2.right := dummyRect2.right + 10;
  328.         for index := 135 downto 0 do
  329.             begin
  330.                 OffsetRect(dummyRect2, -3, 0);
  331.                 OffsetRect(dummyRect3, -3, 0);
  332.                 CopyBits(virginMap, loadMap, dummyRect2, dummyRect2, srcCopy, nil);
  333.                 CopyMask(loadMap, objectsMap, loadMap, dummyRect, objectsRects[34, 1], dummyRect3);
  334.                 CopyBits(loadMap, mainWindow^.portBits, dummyRect2, dummyRect2, srcCopy, mainWindow^.visRgn);
  335.             end;
  336.         PenNormal;
  337.         Delay(120, dummyLong);
  338.         WrapUpaGame;
  339.     end;
  340.  
  341. {=================================}
  342.  
  343.     procedure WelcomeToNextLevel;
  344.         var
  345.             dummyRect, dummyRect2, dummyRect3: Rect;
  346.             index: Integer;
  347.             dummyLong, now: LongInt;
  348.             dummyString, dummyString2: Str255;
  349.     begin
  350.         if ((levelOn = 6) or (levelOn = 11)) then        {Hang on to score in these rooms in case    }
  351.             oldScore := theScore;                            {player gets sucked back to these rooms.    }
  352.         theScore := theScore + (1000 * levelOn) + (300000 div gameTime);        {Here's the score formula    }
  353.         if extraGlider then
  354.             gliderNumber := gliderNumber + 1;
  355.         levelOn := levelOn + 1;
  356.         if LevelOn > maxLevel then
  357.             begin
  358.                 DotheHoopla;
  359.                 DoFinalScore;
  360.             end
  361.         else
  362.             begin
  363.                 SetPort(loadPort);
  364.                 EraseRect(loadMap.bounds);
  365.                 SetRect(dummyRect, 0, 0, 0, 0);
  366.                 ResizeARect(dummyRect, 34);
  367.                 CopyBits(objectsMap, loadMap, objectsRects[34, 0], dummyRect, srcCopy, nil);
  368.                 PenNormal;
  369.                 TextFont(0);
  370.                 TextSize(12);
  371.                 MoveTo(60, 15);
  372.                 dummyString := 'Room ';
  373.                 NumToString(levelOn, dummyString2);
  374.                 dummyString := CONCAT(dummyString, dummyString2, '   Gliders= ');
  375.                 NumToString(gliderNumber, dummyString2);
  376.                 dummyString := CONCAT(dummyString, dummyString2, '   Score= ');
  377.                 NumToString(theScore, dummyString2);
  378.                 dummyString := CONCAT(dummyString, dummyString2);
  379.                 DrawString(dummyString);
  380.                 dummyRect2 := dummyRect;
  381.                 OffsetRect(dummyRect2, 512, 290);
  382.                 dummyRect3 := dummyRect2;
  383.                 dummyRect2.right := dummyRect2.right + 10;
  384.                 now := TickCount + 1;
  385.                 for index := 340 downto 0 do
  386.                     begin
  387.                         now := TickCount + 1;
  388.                         OffsetRect(dummyRect2, -3, 0);
  389.                         OffsetRect(dummyRect3, -3, 0);
  390.                         CopyBits(virginMap, loadMap, dummyRect2, dummyRect2, srcCopy, nil);
  391.                         CopyMask(loadMap, objectsMap, loadMap, dummyRect, objectsRects[34, 1], dummyRect3);
  392.                         CopyBits(loadMap, mainWindow^.portBits, dummyRect2, dummyRect2, srcCopy, mainWindow^.visRgn);
  393.                         if ((index mod 2) = 0) then
  394.                             begin
  395.                                 repeat
  396.                                 until (TickCount >= now);
  397.                                 now := TickCount + 1;
  398.                             end;
  399.                     end;
  400.                 OffsetRect(playerDropRect, -playerDropRect.left + startHori, 0);
  401.                 OffsetRect(shadowDropRect, -shadowDropRect.left + startHori, 0);
  402.                 oldPlayerRect := playerDropRect;
  403.                 oldShadowRect := shadowDropRect;
  404.                 GetSet;
  405.             end;   {end of else}
  406.     end;
  407.  
  408. {=================================}
  409.  
  410.     procedure DetermineObstacle;
  411.         var
  412.             Index: Integer;
  413.             dummyLong: LongInt;
  414.     begin
  415.         case objectArray[whasUp] of
  416.             1:                                                {lift the glider <floor vent>}
  417.                 begin
  418.                     moveVert := moveVert + ventLift;
  419.                 end;
  420.             2:                                                {death to the glider <flames>}
  421.                 begin
  422.                     if (not burning) then
  423.                         begin
  424.                             DoTheSound('flash.snd', highPriority);
  425.                             burning := TRUE;
  426.                             stalling := TRUE;
  427.                             timeOfDeath := gameTime;
  428.                             if (gliderCraft) then
  429.                                 ResizeARect(playerDropRect, 35)
  430.                             else
  431.                                 ResizeARect(playerDropRect, 55);
  432.                         end;
  433.                 end;
  434.             6:                                                 {air blows the glider down to the floor}
  435.                 begin
  436.                     moveVert := moveVert + ductGravity;
  437.                 end;
  438.             7:                                                 {the glider has been sucked back to another room}
  439.                 begin
  440.                     stalling := TRUE;
  441.                     case levelOn of
  442.                         1..5: 
  443.                             begin
  444.                                 levelOn := 1;
  445.                                 theScore := 0;
  446.                             end;
  447.                         6..10: 
  448.                             begin
  449.                                 levelOn := 6;
  450.                                 theScore := oldScore;
  451.                             end;
  452.                         11..15: 
  453.                             begin
  454.                                 levelOn := 11;
  455.                                 theScore := oldScore;
  456.                             end;
  457.                         otherwise
  458.                             begin
  459.                             end;
  460.                     end;
  461.                     DoTheSound('ductsuck.snd', highPriority);
  462.                     Delay(40, dummyLong);
  463.                     ResetGliderPos;
  464.                     GetSet;
  465.                     DoTheSound('ductdump.snd', highPriority);
  466.                 end;
  467.             8:                                                 {the glider has succeeded in a time bonus <clock>}
  468.                 begin
  469.                     if (not extraTime) and (not burning) and (not crushed) then
  470.                         begin
  471.                             DoTheSound('bonus.snd', highPriority);
  472.                             extraTime := TRUE;
  473.                             gameTime := 0;
  474.                             SetPort(MainWindow);
  475.                             for Index := 1 to 12 do
  476.                                 begin
  477.                                     InvertRect(eventArray[whasUp]);
  478.                                     Delay(2, dummyLong);
  479.                                 end;
  480.                         end;
  481.                 end;
  482.             9:                                                  {the glider gets another 'ship' <folded piece of paper>}
  483.                 begin
  484.                     if (not extraGlider) then
  485.                         begin
  486.                             DoTheSound('bonus.snd', highPriority);
  487.                             extraGlider := TRUE;
  488.                             SetPort(MainWindow);
  489.                             for Index := 1 to 12 do
  490.                                 begin
  491.                                     InvertRect(eventArray[whasUp]);
  492.                                     Delay(2, dummyLong);
  493.                                 end;
  494.                         end;
  495.                 end;
  496.             10:                                               {excellent - the air is turned on <thermostat>}
  497.                 begin
  498.                     if (ventLift = 0) then
  499.                         begin
  500.                             DoTheSound('bonus.snd', highPriority);
  501.                             ventLift := floorFast;
  502.                             SetPort(MainWindow);
  503.                             for Index := 1 to 12 do
  504.                                 begin
  505.                                     InvertRect(eventArray[whasUp]);
  506.                                     Delay(2, dummyLong);
  507.                                 end;
  508.                         end;
  509.                 end;
  510.             11: 
  511.                 begin
  512.                     if (darkOn) and (switchUntouched) then
  513.                         begin
  514.                             DoTheSound('bonus.snd', highPriority);
  515.                             darkOn := FALSE;
  516.                             switchUntouched := FALSE;
  517.                             SetPort(MainWindow);
  518.                             for Index := 1 to 12 do
  519.                                 begin
  520.                                     InvertRect(eventArray[whasUp]);
  521.                                     Delay(2, dummyLong);
  522.                                 end;
  523.                             Update_GliderMain;
  524.                         end;
  525.                 end;
  526.             12:         {glider has landed upon a surface like a shelf or table - now display crushed glider    }
  527.                 begin
  528.                     if (not burning) and (not crushed) then
  529.                         begin
  530.                             DoTheSound('crunch.snd', highPriority);
  531.                             crushed := TRUE;
  532.                             stalling := TRUE;
  533.                             timeOfDeath := gameTime;
  534.                             if (gliderCraft) then
  535.                                 ResizeARect(playerDropRect, 35)
  536.                             else
  537.                                 ResizeARect(playerDropRect, 55);
  538.                         end;
  539.                 end;
  540.             otherwise
  541.                 begin
  542.                 end;
  543.         end;  {case}
  544.     end;
  545.  
  546. {=================================}
  547.  
  548.     procedure ComputeStatus;
  549.         var
  550.             Index: Integer;
  551.             dummy: Rect;
  552.     begin
  553.         for Index := 1 to totalObjects do
  554.             begin
  555.                 if SectRect(vitalArea, eventArray[Index], dummy) then
  556.                     DetermineObstacle(Index);
  557.             end;
  558.         if (not SectRect(vitalArea, playArea, dummy)) then        {heading out-of bounds}
  559.             begin
  560.                 if (playerDropRect.top > 280) and (not crushed) and (not burning) then
  561.                     begin
  562.                         DoTheSound('crunch.snd', highPriority);
  563.                         crushed := TRUE;
  564.                         stalling := TRUE;
  565.                         timeOfDeath := gameTime;
  566.                         if (gliderCraft) then
  567.                             ResizeARect(playerDropRect, 35)
  568.                         else
  569.                             ResizeARect(playerDropRect, 55);
  570.                     end;
  571.                 if (playerDropRect.top < 10) then
  572.                     begin
  573.                         moveVert := -ventLift;
  574.                     end;
  575.                 if (playerDropRect.left < -17) then
  576.                     begin
  577.                         moveHori := thrust;
  578.                     end;
  579.                 if (playerDropRect.left > 510) then
  580.                     begin
  581.                         WelcomeToNextLevel;
  582.                     end;
  583.             end;  {end of if (not SetRect...}
  584.     end;
  585.  
  586. {=================================}
  587.  
  588.     procedure DoDyingDisplay;
  589.     begin
  590.         if (playerDropRect.bottom > 295) then
  591.             DoGliderBitesIt
  592.         else
  593.             begin
  594.                 if (burning) then
  595.                     begin
  596.                         burnMode := DoRandom(2);
  597.                         if (gliderCraft) then
  598.                             ResizeARect(playerDropRect, burnMode + 37)
  599.                         else
  600.                             ResizeARect(playerDropRect, burnMode + 56);
  601.                         if (playerDropRect.top > 275) then
  602.                             begin
  603.                                 OffsetRect(playerDropRect, 0, 276 - playerDropRect.top);
  604.                             end;
  605.                     end        {end-if burning}
  606.                 else
  607.                     begin
  608.                         if (playerDropRect.bottom < 300) then
  609.                             OffsetRect(playerDropRect, 0, gravity * 2);
  610.                     end;
  611.             end;
  612.     end;
  613.  
  614. {=================================}
  615.  
  616.     procedure DoCopter;
  617.         var
  618.             overlapping: Boolean;
  619.             index, index2, hori: Integer;
  620.             dummyRect: Rect;
  621.     begin
  622.         for index := 1 to numberOfCopters do
  623.             begin
  624.                 case copterMode[index, 0] of
  625.                     0: 
  626.                         begin
  627.                         end;
  628.                     1:         {in mode=1 the helicopter twirls down until it's off screen or hit the player}
  629.                         begin
  630.                             copterMode[index, 1] := copterMode[index, 1] + 1;
  631.                             if (copterMode[index, 1] > 8) then
  632.                                 copterMode[index, 1] := 1;
  633.                             OffsetRect(coptersRects[index, 0], -2 * advanceRate, gravity);
  634.                             UnionRect(coptersRects[index, 0], coptersRects[index, 1], dummyRect);
  635.                             CopyBits(virginMap, loadMap, dummyRect, dummyRect, srcCopy, nil);
  636.                             CopyMask(objectsMap, objectsMap, loadMap, objectsRects[copterMode[index, 1] + 14, 0], objectsRects[copterMode[index, 1] + 14, 1], coptersRects[index, 0]);
  637.                             CopyBits(loadMap, mainWindow^.portBits, dummyRect, dummyRect, srcCopy, mainWindow^.visRgn);
  638.                             coptersRects[index, 1] := coptersRects[index, 0];    {set "old rect" to current rect}
  639.                             if (SectRect(coptersRects[index, 0], vitalArea, dummyRect) and (not crushed) and (not burning)) then
  640.                                 begin
  641.                                     DoTheSound('boom.snd', highPriority);
  642.                                     crushed := TRUE;
  643.                                     stalling := TRUE;
  644.                                     timeOfDeath := gameTime;
  645.                                     if (gliderCraft) then
  646.                                         ResizeARect(playerDropRect, 35)
  647.                                     else
  648.                                         ResizeARect(playerDropRect, 55);
  649.                                 end;
  650.                             if (coptersRects[index, 0].right < 0) then    {i.e. if the copter has gone off the left..    }
  651.                                 copterMode[index, 0] := DoRandom((18 - levelOn) * 4) + 10;
  652.                         end;
  653.                     2:         {when the copter reaches mode=2, then it has burst on the scene from above}
  654.                         begin
  655.                             SetRect(coptersRects[index, 0], 0, 0, 0, 0);
  656.                             ResizeARect(coptersRects[index, 0], 15);
  657.                             repeat
  658.                                 overlapping := FALSE;
  659.                                 hori := DoRandom(300) + 220;
  660.                                 OffsetRect(coptersRects[index, 0], hori, -36);
  661.                                 for index2 := 1 to numberOfCopters do
  662.                                     begin
  663.                                         if (index2 <> index) then
  664.                                             if SectRect(coptersRects[index, 0], coptersRects[index2, 0], dummyRect) then
  665.                                                 overlapping := TRUE;
  666.                                     end;
  667.                             until (not overlapping);
  668.                             coptersRects[index, 1] := coptersRects[index, 0];    {set "old rect" to current rect}
  669.                             copterMode[index, 0] := 1;        {put copter in mode 1 (see above)}
  670.                             copterMode[index, 1] := 1;        {the actual cycle in it's spin is 1}
  671.                         end;
  672.                     otherwise    {the copter begins at an arbitrary and high mode number, each game cycle}
  673.                         begin        {this gets decremented until it reaches mode=2, then it appears}
  674.                             copterMode[index, 0] := copterMode[index, 0] - 1;
  675.                         end;
  676.                 end;        {case copterMode[index, 0] of}
  677.             end;
  678.     end;
  679.  
  680. {=================================}
  681.  
  682.     procedure DoDrip;
  683.         var
  684.             dummyRect: Rect;
  685.     begin
  686.         case dripMode of
  687.             0:                {In this mode, the drip has changed appearance and needs to be drawn                }
  688.                 begin
  689.                     SetRect(dripDropRect, 0, 0, 0, 0);        {First, reset the rectangle for the drip                }
  690.                     ResizeARect(dripDropRect, dripCycle);    {Resize it according to which drip is to be drawn    }
  691.                     OffsetRect(dripDropRect, 350, 5);        {Move it so that it resides on the stained ceiling    }
  692.                     CopyBits(virginMap, loadMap, dripDropRect, dripDropRect, srcCopy, nil);    {Draw it        }
  693.                     CopyMask(objectsMap, objectsMap, loadMap, objectsRects[dripCycle, 0], objectsRects[dripCycle, 1], dripDropRect);
  694.                     CopyBits(loadMap, mainWindow^.portBits, dripDropRect, dripDropRect, srcCopy, nil);
  695.                     dripMode := 1;                                {Advance the drip mode to 1 for next game pass    }
  696.                 end;
  697.             1..18:        {The drip is idling while drop builds up.  It provides a time delay                    }
  698.                 begin
  699.                     dripMode := dripMode + advanceRate;    {All we do is advance the mode until it reaches    }
  700.                 end;                                            {19 or 20 (advanceRate is 2 for fast mode).        }
  701.             19..20:                                             {We're through idling.  Time to advance the drip.    }
  702.                 begin
  703.                     dripCycle := dripCycle + 1;                {Increment the cycle of the drip (it's swelling).    }
  704.                     if (dripCycle = 25) then                    {If the cycle is 25, then the drop has formed        }
  705.                         begin                                        {We need to retract the drip first and draw it.        }
  706.                             CopyBits(virginMap, loadMap, dripDropRect, dripDropRect, srcCopy, nil);
  707.                             CopyMask(objectsMap, objectsMap, loadMap, objectsRects[25, 0], objectsRects[25, 1], dripDropRect);
  708.                             CopyBits(loadMap, mainWindow^.portBits, dripDropRect, dripDropRect, srcCopy, nil);
  709.                             dripMode := 21;                            {And then advance the drip mode to 21.                }
  710.                         end
  711.                     else                                            {If the drop has not fallen, then we simply have a    }
  712.                         dripMode := 0;                                {drip that has swelled.  We need to draw it.            }
  713.                 end;                                            {Going back to mode=0 will draw the new drip        }
  714.             21:         {In this mode, the drop has freed itself and needs to be set up.                            }
  715.                 begin
  716.                     CopyBits(virginMap, loadMap, dripDropRect, dripDropRect, srcCopy, nil);
  717.                     CopyMask(objectsMap, objectsMap, loadMap, objectsRects[26, 0], objectsRects[26, 1], dripDropRect);
  718.                     CopyBits(loadMap, mainWindow^.portBits, dripDropRect, dripDropRect, srcCopy, nil);
  719.                     SetRect(dripDropRect, 0, 0, 0, 0);        {We reset the bounding rectangle for the newly    }
  720.                     ResizeARect(dripDropRect, 27);            {freed water drop.                                        }
  721.                     OffsetRect(dripDropRect, 358, 20);        {Then we move it a little down from the ceiling.    }
  722.                     oldDripRect := dripDropRect;                {The old Rect initially where the current drip is.    }
  723.                     CopyBits(virginMap, loadMap, dripDropRect, dripDropRect, srcCopy, nil);    {And draw    }
  724.                     CopyMask(objectsMap, objectsMap, loadMap, objectsRects[27, 0], objectsRects[27, 1], dripDropRect);
  725.                     CopyBits(loadMap, mainWindow^.portBits, dripDropRect, dripDropRect, srcCopy, nil);
  726.                     dripCycle := 26;                            {The water still on the ceiling is the drip corres-    }
  727.                     dripMode := 22;                                {sponding to rectangle#26.  Bump the mode to 22.    }
  728.                     DoTheSound('drip.snd', highPriority);
  729.                 end;
  730.             22:         {In this mode we track the falling drop of water, checking for the floor or glider.    }
  731.                 begin
  732.                     UnionRect(dripDropRect, oldDripRect, dummyRect);    {dummy = union of the old and new    }
  733.                     CopyBits(virginMap, loadMap, dummyRect, dummyRect, srcCopy, nil);    {get background    }
  734.                     CopyMask(objectsMap, objectsMap, loadMap, objectsRects[27, 0], objectsRects[27, 1], dripDropRect);
  735.                     CopyBits(loadMap, mainWindow^.portBits, dummyRect, dummyRect, srcCopy, nil);
  736.                     if (SectRect(dummyRect, vitalArea, dummyRect)) then    {Has it hit the glider?            }
  737.                         begin
  738.                             DoGliderBitesIt;
  739.                         end;
  740.                     oldDripRect := dripDropRect;
  741.                     OffsetRect(dripDropRect, 0, gravity * 13);    {This drop falls pretty tootin' fast!  13        }
  742.                     if (dripDropRect.bottom > 300) then        {times faster than the glider falls.  If it has      }
  743.                         dripMode := 23;                            {fallen past 300 in pixels, it has hit the ground.    }
  744.                 end;
  745.             23:         {This is for the hit-the-ground drop.  All we do is cover the old drop on the floor    }
  746.                 begin    {and set the mode and cycle back to the start for another drip. What we do is grab    }
  747.                     UnionRect(dripDropRect, oldDripRect, dummyRect);    {a patch of the background to cover    }
  748.                     CopyBits(virginMap, mainWindow^.portBits, dummyRect, dummyRect, srcCopy, nil);    {it.    }
  749.                     dripMode := 0;
  750.                     dripCycle := 23;
  751.                 end;
  752.             otherwise            {And that's it.  One case statement to run the drip through it's various    }
  753.                 begin                {dripping stages of animation.  Easy, organized, difficult to understand.    }
  754.                 end;                {Walk through it though.  See what happens as the mode and cycle change.    }
  755.         end;        {end case dripMode of}
  756.     end;
  757.  
  758. {=================================}
  759.  
  760.     procedure DoCat;
  761.         var
  762.             switch, tempSide: Integer;
  763.             dummyRect: Rect;
  764.  
  765.         procedure RightSideARect (cycle: Integer);
  766.             var
  767.                 tempRight: Integer;
  768.                 dummyRect: Rect;
  769.         begin
  770.             oldPawRect := pawRect;
  771.             tempRight := pawRect.right;
  772.             pawRect := objectsRects[cycle, 0];
  773.             OffsetRect(pawRect, tempRight - pawRect.right, -16);
  774.             UnionRect(pawRect, oldPawRect, dummyRect);
  775.             CopyBits(virginMap, loadMap, dummyRect, dummyRect, srcCopy, nil);
  776.             CopyMask(objectsMap, objectsMap, loadMap, objectsRects[cycle, 0], objectsRects[cycle, 1], pawRect);
  777.             CopyBits(loadMap, mainWindow^.portBits, dummyRect, dummyRect, srcCopy, nil);
  778.         end;
  779.  
  780.     begin
  781.         case catMode of
  782.             0:     {In this mode the cat has moved it's tail down and it needs to be redrawn    }
  783.                 begin
  784.                     CopyBits(virginMap, loadMap, catBodyRect, catBodyRect, srcCopy, nil);
  785.                     CopyMask(objectsMap, objectsMap, loadMap, objectsRects[28, 0], objectsRects[28, 1], catBodyRect);
  786.                     CopyBits(loadMap, mainWindow^.portBits, catBodyRect, catBodyRect, srcCopy, nil);
  787.                     catMode := 1;
  788.                 end;
  789.             1:     {This is the tail down idle mode    }
  790.                 begin
  791.                     switch := DoRandom(20 div advanceRate);
  792.                     if (switch = 0) then
  793.                         catMode := 2;
  794.                     if (SectRect(vitalArea, dangerRect, dummyRect)) then
  795.                         catMode := 4;
  796.                 end;
  797.             2:     {In this mode the cat has swung it's tail up and it needs to be drawn    }
  798.                 begin
  799.                     CopyBits(virginMap, loadMap, catBodyRect, catBodyRect, srcCopy, nil);
  800.                     CopyMask(objectsMap, objectsMap, loadMap, objectsRects[29, 0], objectsRects[29, 1], catBodyRect);
  801.                     CopyBits(loadMap, mainWindow^.portBits, catBodyRect, catBodyRect, srcCopy, nil);
  802.                     catMode := 3;
  803.                 end;
  804.             3:     {This is the tail up idle mode        }
  805.                 begin
  806.                     switch := DoRandom(20 div advanceRate);
  807.                     if (switch = 0) then
  808.                         catMode := 0;
  809.                     if (SectRect(vitalArea, dangerRect, dummyRect)) then
  810.                         catMode := 4;
  811.                 end;
  812.             4:     {This is the mode where the cat is going to swat with its paw        }
  813.                 begin
  814.                     RightSideARect(30);
  815.                     catMode := 5;
  816.                 end;
  817.             5..6:     {In this mode the cat is swatting his paw    }
  818.                 begin
  819.                     catMode := catMode + advanceRate;
  820.                 end;
  821.             7..8:     {In this mode we resize the pawRect for the next cycle of swatting    }
  822.                 begin
  823.                     RightSideARect(31);
  824.                     catMode := 9;
  825.                 end;
  826.             9..10:     {In this mode the cat is swatting his paw    }
  827.                 begin
  828.                     catMode := catMode + advanceRate;
  829.                 end;
  830.             11..12:     {In this mode we resize the pawRect for the next cycle of swatting    }
  831.                 begin
  832.                     RightSideARect(32);
  833.                     catMode := 13;
  834.                 end;
  835.             13..14:     {In this mode the cat is swatting his paw - it is fully extended    }
  836.                 begin
  837.                     catMode := catMode + advanceRate;
  838.                     if (SectRect(vitalArea, escapeRect, dummyRect)) then
  839.                         begin
  840.                             crushed := TRUE;
  841.                             stalling := TRUE;
  842.                             timeOfDeath := gameTime;
  843.                             if (gliderCraft) then
  844.                                 ResizeARect(playerDropRect, 35)
  845.                             else
  846.                                 ResizeARect(playerDropRect, 55);
  847.                         end;
  848.                 end;
  849.             15..16:     {In this mode we resize the pawRect for the next cycle of swatting    }
  850.                 begin
  851.                     RightSideARect(33);
  852.                     catMode := 17;
  853.                 end;
  854.             17..18:     {In this mode the cat is swatting his paw - it is being retracted    }
  855.                 begin
  856.                     catMode := catMode + advanceRate;
  857.                 end;
  858.             19..20:     {In this mode the cat is going to go into refractory mode    }
  859.                 begin
  860.                     dummyRect := catBodyRect;
  861.                     dummyRect.left := dummyRect.left - 30;
  862.                     CopyBits(virginMap, loadMap, dummyRect, dummyRect, srcCopy, nil);
  863.                     CopyMask(objectsMap, objectsMap, loadMap, objectsRects[28, 0], objectsRects[28, 1], catBodyRect);
  864.                     CopyBits(loadMap, mainWindow^.portBits, dummyRect, dummyRect, srcCopy, nil);
  865.                     catMode := 21;
  866.                 end;
  867.             21..50:     {In this mode the cat is in it's refractory period and the only safe time to escape    }
  868.                 begin
  869.                     catMode := catMode + advanceRate;
  870.                     if ((SectRect(vitalArea, escapeRect, dummyRect)) and (not crushed)) then
  871.                         WelcomeToNextLevel;
  872.                 end;
  873.             otherwise    {We reset the cat to a mode=0}
  874.                 begin
  875.                     catMode := 0;
  876.                 end;
  877.         end;    {case catMode of}
  878.         if (playerDropRect.right > 480) and (not crushed) then
  879.             begin
  880.                 crushed := TRUE;
  881.                 stalling := TRUE;
  882.                 timeOfDeath := gameTime;
  883.                 if (gliderCraft) then
  884.                     ResizeARect(playerDropRect, 35)
  885.                 else
  886.                     ResizeARect(playerDropRect, 55);
  887.             end;
  888.     end;
  889.  
  890. {=================================}
  891.  
  892. end.